package com.sprouting.personal.service;

import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sprouting.personal.dao.BillDao;
import com.sprouting.personal.dao.ExpenseMemberDao;
import com.sprouting.personal.model.entity.Bill;
import com.sprouting.personal.model.entity.ExpenseMember;
import com.sprouting.personal.model.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * 账单
 *
 * @author ：LX（长沙麓谷）
 * @date 创建时间： 2022/12/27 9:32
 */
@Service
@Slf4j
public class BillService extends ServiceImpl<BillDao, Bill> {

    @Resource
    private BillDao billDao;
    @Resource
    private ExpenseMemberDao expenseMemberDao;


    /**
     * 根据组ID查询账单
     * @param groupId 组ID
     * @param page 分页参数
     * @return
     */
    public Page<Bill> getBillByGroupId(Page page, String groupId) {
        return billDao.getBillByGroupId(page, groupId);
    }

    /**
     * 根据组ID查询账单 只查询一条出来
     * @param groupId 组ID
     * @return
     */
    public Bill getBillByGroupIdLimit1(String groupId) {
        return billDao.getBillByGroupIdLimit1(groupId);
    }

    /**
     * 保存账单
     * @param bill 账单
     * @param expenseMemberList 使用人
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveBill(Bill bill, List<ExpenseMember> expenseMemberList) {
        billDao.insert(bill);
        for (ExpenseMember expenseMember : expenseMemberList){
            expenseMemberDao.insert(expenseMember);
        }
    }

    /**
     * 更新账单
     * @param bill 账单
     * @param expenseMemberList 使用人
     */
    @Transactional(rollbackFor = Exception.class)
    public void updBill(Bill bill, List<ExpenseMember> expenseMemberList) {
        billDao.updateById(bill);

        // 删除旧的
        LambdaQueryWrapper<ExpenseMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ExpenseMember::getBillId, bill.getId());
        expenseMemberDao.delete(wrapper);

        // 重新添加
        for (ExpenseMember expenseMember : expenseMemberList){
            expenseMemberDao.insert(expenseMember);
        }
    }

    /**
     * 删除账单
     * @param id 账单ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void delBill(String id) {
        billDao.deleteById(id);

        LambdaQueryWrapper<ExpenseMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ExpenseMember::getBillId, id);
        expenseMemberDao.delete(wrapper);
    }

    /**
     * 分页查询账单
     * @param page 分页参数
     * @param billQuery 查询参数
     * @return
     */
    public Page<BillVo> getBillPageList(Page page, BillQuery billQuery) {
        return billDao.getBillPageList(page, billQuery);
    }

    /**
     * 获取最常用的五个账单类型
     * @param userId 当前用户ID
     * @return
     */
    public List<String> getMostCommonlyUsedType(String userId) {
        return billDao.getMostCommonlyUsedType(userId);
    }

    /**
     * 解绑账单组
     * @param id 账单组ID
     * @param userId 当前登录用户ID
     * @param date 当前时间
     */
    public void updBillUnbinding(String id, String userId, Date date) {
        billDao.updBillUnbinding(id, userId, date);
    }

    /**
     * 获取一段时间的开支情况
     * @param userId 登录用户
     * @param dateTimeStart 开始时间
     * @param dateTimeEnd 结束时间
     * @return
     */
    public BillUsage getExpenditure(String userId, DateTime dateTimeStart, DateTime dateTimeEnd) {
        return billDao.getExpenditure(userId, dateTimeStart, dateTimeEnd);
    }

    /**
     * 获取一段时间的开支情况
     * {@link BillService#getExpenditure(String, DateTime, DateTime)} 和这个类型
     * @param billQuery 查询参数
     * @return
     */
    public BillUsage getExpenditureQuery(BillQuery billQuery) {
        return billDao.getExpenditureQuery(billQuery);
    }

    /**
     * 查询账单分组情况
     * @param userId 登录用户
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param incomeOrExpenditure 是支出还是收入 {@link com.sprouting.personal.interfaces.common.Constant.RevenueExpense}
     * @return
     */
    public List<BillGroupExpenses> getPercentageGroup(String userId, DateTime startTime, DateTime endTime, Integer incomeOrExpenditure) {
        return billDao.getPercentageGroup(userId, startTime, endTime, incomeOrExpenditure);
    }

    /**
     * 查询账单分组情况
     * 因为要查询对应的人员账单，导致必须加子查询，否则数据有问题
     * {@link BillService#getPercentageGroup(String, DateTime, DateTime, Integer)}  相似
     * @param billQuery 查询参数
     * @return
     */
    public List<BillGroupExpenses> getPercentageGroupQuery(BillQuery billQuery) {
        return billDao.getPercentageGroupQuery(billQuery);
    }

    /**
     * 获取每天的支出数量和笔数
     * @param userId 登录用户
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return
     */
    public List<BillDailyExpenditure> getExpenditureTrend(String userId, DateTime startTime, DateTime endTime) {
        return billDao.getExpenditureTrend(userId, startTime, endTime);
    }

    /**
     * 获取指定时间范围内每个月的支出数量和笔数
     * @param userId 登录用户
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return
     */
    public List<BillMonthExpenses> getExpendituresForEachMonthYear(String userId, DateTime startTime, DateTime endTime) {
        return billDao.getExpendituresForEachMonthYear(userId, startTime, endTime);
    }

    /**
     * 获取历年支出情况
     * @param userId 登录用户
     * @param startTime 开始时间
     * @param entTime 结束时间
     * @return
     */
    public List<BillYearExpenses> getExpenditureOverYears(String userId, DateTime startTime, DateTime entTime) {
        return billDao.getExpenditureOverYears(userId, startTime, entTime);
    }

    /**
     * 获取每个人一段时间内的支出收入情况
     * @param userId 登录用户
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return
     */
    public List<BillUser> getExpenditurePerson(String userId, DateTime startTime, DateTime endTime) {
        return billDao.getExpenditurePerson(userId, startTime, endTime);
    }

    /**
     * 获取每个人一段时间内的支出收入情况
     * {@link BillService#getExpenditurePerson(String, DateTime, DateTime)} 和这个相比多了一些参数
     * @param billQuery 查询参数
     * @return
     */
    public List<BillUser> getExpenditurePersonQuery(BillQuery billQuery) {
        return billDao.getExpenditurePersonQuery(billQuery);
    }

    /**
     * 过去一段时间每个月每人的支出情况
     * @param userId 登录用户
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return
     */
    public List<BillUserMonth> getMonthlyExpenditurePerPersonInThePast(String userId, DateTime startTime, DateTime endTime) {
        return billDao.getMonthlyExpenditurePerPersonInThePast(userId, startTime, endTime);
    }

    /**
     * 统计根据该查询条件得到的收入和支出结果
     * @param billQuery 查询条件
     * @return
     */
    public BillExpensesAndReceipts getBillCountList(BillQuery billQuery) {
        return billDao.getBillCountList(billQuery);
    }

}
